#ifndef WEBSERVER_H
#define WEBSERVER_H

#include <unordered_map>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "epoller.h"
#include "../log/log.h"
#include "../pool/threadpool.h"
#include "../pool/sqlconnpool.h"
#include "../pool/sqlconnRAII.h"
#include "../timer/heaptimer.h"
#include "../http/httpconn.h"

class WebServer {
public:
    WebServer(int port, int trigMode, int timeOutMs, bool optLinger,
              int sqlPort, const char* sqlUser, const char* sqlPwd,
              const char* dbName, int connPoolNum, int threadNum,
              bool openLog, int logLevel, int logQueSize);
    ~WebServer();

    void start();
private:
    bool initSocket();
    void initEventMode(int trigMode);
    void addClient(int fd, sockaddr_in addr);

    void dealListen();
    void dealWrite(HttpConn* client);
    void dealRead(HttpConn* client);

    void sendError(int fd, const char* info);
    void extentTime(HttpConn* client);
    void closeConn(HttpConn* client);

    void onRead(HttpConn* client);
    void onWrite(HttpConn* client);
    void onProcess(HttpConn* client);

    static const int MAX_FD = 65536;
    static int setFdNonBlock(int fd);
private:
    int port_;          // 端口
    bool openLinger_;   // 控制套接字关闭时的行为
    int timeOutMs_;     // 超时时间
    bool isClose_;      // 是否关闭
    int listenFd_;      // 监听客户端
    char* srcDir_;      // 服务器资源的根目录

    uint32_t listenEvent_;  // 控制监听套接字的事件触发模式
    uint32_t connEvent_;    // 控制客户端连接的事件触发模式

    std::unique_ptr<HeapTimer> timer_;          // 定时器
    std::unique_ptr<ThreadPool> threadPool_;    // 线程池
    std::unique_ptr<Epoller> epoller_;          // epoll实例
    std::unordered_map<int, HttpConn> user_;    // fd/客户端
};

#endif